When there are 3 or more windows in WorkspaceLayout, showing or hiding
window preview overlay in some certain orders could cause
inconsistencies in windows' vertical arrangement.
Let's take window A, B, C as an example. Initially, A is above B and B
is above C in workspace layout like this: A -> B -> C.
After opening activities, user could:
1. Move cursor to B preview, which would move B above all in layout:
B -> A -> C
2. Move cursor from B to C preview. When C's showOverlay() is called
before B's hideOverlay(), _restack() would move C above all and don't
change B's arrangement:
C -> B -> A
3. Finally, move cursor away from C's preview:
B -> A -> C
In this case, when user closes Activities, they would see window
stacking wrong for a while.
This commit adds some extra logic in _restack, checking the
_stackAbove's _stackAbove when this._stackAbove._overlayShown is true.
Though it's still not guaranteed to be always consistent as there could
be several WindowPreview with _overlayShown as true if pointer moves
really fast, this helps avoid glitches in many cases.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/4638.
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3460>
// with a new one on the target workspace.
const parent = this.get_parent();
if (parent !== null) {
- if (this._overlayShown)
+ if (this._overlayShown) {
parent.set_child_above_sibling(this, null);
- else if (this._stackAbove === null)
+ } else if (this._stackAbove === null) {
parent.set_child_below_sibling(this, null);
- else if (!this._stackAbove._overlayShown)
+ } else if (!this._stackAbove._overlayShown) {
parent.set_child_above_sibling(this, this._stackAbove);
+ } else {
+ // This window shall still be above this._stackAbove._stackAbove
+ const above = this._stackAbove._stackAbove;
+ if (above === null)
+ parent.set_child_below_sibling(this, null);
+ else
+ parent.set_child_above_sibling(this, above);
+ }
}
}